package io.elegant.widgets

import android.graphics.BitmapFactory
import android.view.ViewGroup
import android.widget.ImageView
import com.google.protobuf.Any
import io.elegant.sessions.BaseSession
import io.elegant.toAny
import io.elegant.toStringValueOrNull
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.launch
import okhttp3.*
import okio.IOException
import java.io.File
import java.io.InputStream
import java.net.URL
import kotlin.reflect.KClass

class ImageWidget<T: ImageView>(
    private val session: BaseSession,
    group: ViewGroup,
    private val cs: CoroutineScope
): BaseWidget<T>(session, group, cs) {
    private var src: String? = null
    private var client: OkHttpClient? = null
    override fun create(clazz: KClass<T>, sessionId: Long, futureId: Long, vararg argv: Any) {
        super.create(clazz, sessionId, futureId, *argv)
        client = OkHttpClient
            .Builder()
            .build()
        setSrc(sessionId, futureId, *argv.sliceArray(4..<5))
    }
    override fun destroy() {
        client = null
        super.destroy()
    }
    override fun onReceive(name: String, sessionId: Long, futureId: Long, vararg argv: Any): Boolean {
        if (when(name) {
                "getSrc" -> getSrc(sessionId, futureId)
                "setSrc" -> setSrc(sessionId, futureId, *argv)
                else -> null
        } != null)
            return true
        return super.onReceive(name, sessionId, futureId, *argv)
    }
    private fun getSrc(sessionId: Long, futureId: Long) {
        onGetSrc(src.toAny(), sessionId, futureId)
    }
    private fun onGetSrc(src: Any, sessionId: Long, futureId: Long) = session.apply {
        sendAction("onGetSrc", sessionId, futureId, src)
    }
    private fun setSrc(sessionId: Long, futureId: Long, vararg argv: Any) {
        src = argv[0].toStringValueOrNull()
        // 从网络URL加载图片
        val ctx = view?.context ?: return
        if (src.isNullOrBlank()) {
            view?.setImageBitmap(null)
            return
        }
        fun read(stream: InputStream) = cs.launch {
            // 解码图片
            try {
                val bitmap = BitmapFactory.decodeStream(stream) ?: return@launch
                view?.setImageBitmap(bitmap)
            } catch (e: OutOfMemoryError) {
                session.onError(e, sessionId, futureId)
                e.printStackTrace()
            }
        }
        val url = URL(src)
        val name = url.path.drop(url.path.indexOfLast { it == '/' } + 1)
        val file = File(ctx.cacheDir, name)
        file
            .takeIf { it.exists() }
            ?.inputStream()
            ?.use {
                read(it)
                return
            }
        // 打开网络传输流
        val req = Request
            .Builder()
            .url(url)
            .build()
        client
            ?.newCall(req)
            ?.enqueue(object: Callback {
                override fun onFailure(call: Call, e: IOException) = cs.launch {
                    session.onError(e, sessionId, futureId)
                }.let {  }
                override fun onResponse(call: Call, response: Response) {
                    val stream  =  response.body.byteStream()
                    file
                        .outputStream()
                        .use (stream::copyTo)
                    file
                        .inputStream()
                        .use (::read)
                }
            })
    }
}